package com.xuhao.didi.oksocket;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.xuhao.didi.core.iocore.interfaces.ISendable;
import com.xuhao.didi.core.pojo.OriginalData;
import com.xuhao.didi.core.utils.SLog;
import com.xuhao.didi.oksocket.btnview.LogUtil;
import com.xuhao.didi.oksocket.btnview.Ripple;
import com.xuhao.didi.oksocket.data.MsgDataBean;
import com.xuhao.didi.socket.client.sdk.OkSocket;
import com.xuhao.didi.socket.common.interfaces.common_interfacies.server.*;
import com.xuhao.didi.socket.server.action.ServerActionAdapter;
import com.xuhao.didi.socket.server.impl.OkServerOptions;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Component;
import ohos.agp.components.Text;
import ohos.agp.window.service.WindowManager;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.miscservices.pasteboard.PasteData;
import ohos.miscservices.pasteboard.SystemPasteboard;
import ohos.net.NetHandle;
import ohos.net.NetManager;
import ohos.wifi.IpInfo;
import ohos.wifi.WifiDevice;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.util.*;

public class MainAbility extends Ability implements Component.ClickedListener, IClientIOCallback {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "onClientIOServer");
    private Ripple mSimpleBtn;

    private Ripple mComplexBtn;

    private Ripple mServerBtn;

    private Ripple mAdminBtn;

    private IServerManager mServerManager;

    private Text mIPTv;

    private int mPort = 8080;

    private EventHandler mHandler;

    private int mTitleColor = -1;
    private String mServerLog = "ServerCallback";

    @Override
    public void onStart(Intent intent) {
        WindowManager.getInstance().getTopWindow().get().setStatusBarColor(mTitleColor);
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initView();
    }

    private void initView() {
        mSimpleBtn = (Ripple) findComponentById(ResourceTable.Id_btn1);
        mComplexBtn = (Ripple) findComponentById(ResourceTable.Id_btn2);
        mServerBtn = (Ripple) findComponentById(ResourceTable.Id_btn3);
        mAdminBtn = (Ripple) findComponentById(ResourceTable.Id_admin);
        mIPTv = (Text) findComponentById(ResourceTable.Id_ip);
        OkServerOptions.setIsDebug(true);
        OkServerOptions.setIsDebug(true);
        SLog.setIsDebug(true);
        mIPTv.setText("当前IP(Local Device IP):" + getIpAddress());
        mServerBtn.setClickedListener(this);
        mComplexBtn.setClickedListener(this);
        mAdminBtn.setClickedListener(this);
        mSimpleBtn.setClickedListener(this);
        mIPTv.setClickedListener(this);
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        mServerManager = OkSocket.server(mPort).registerReceiver(new ServerActionAdapter() {
            @Override
            public void onServerListening(int serverPort) {
                super.onServerListening(serverPort);
                flushServerText();
            }

            @Override
            public void onClientConnected(IClient client, int serverPort, IClientPool clientPool) {
                LogUtil.i(mServerLog + Thread.currentThread().getName() + " onClientConnected,serverPort:"
                        + serverPort + "--ClientNums:" + clientPool.size() + "--ClientTag:" + client.getUniqueTag());
                client.addIoCallback(MainAbility.this);
            }

            @Override
            public void onClientDisconnected(IClient client, int serverPort, IClientPool clientPool) {
                LogUtil.i(mServerLog + Thread.currentThread().getName() + " onClientDisconnected,serverPort:"
                        + serverPort + "--ClientNums:" + clientPool.size() + "--ClientTag:" + client.getUniqueTag());
                client.removeIoCallback(MainAbility.this);
            }

            @Override
            public void onServerWillBeShutdown(int serverPort, IServerShutdown shutdown,
                                               IClientPool clientPool, Throwable throwable) {
                LogUtil.i(mServerLog + Thread.currentThread().getName()
                        + " onServerWillBeShutdown,serverPort:" + serverPort + "--ClientNums:" + clientPool.size());
                shutdown.shutdown();
            }

            @Override
            public void onServerAlreadyShutdown(int serverPort) {
                LogUtil.i("ServerCallback" + Thread.currentThread().getName() + " onServerAlreadyShutdown,serverPort:" + serverPort);
                flushServerText();
            }
        });
    }

    private void flushServerText() {
        if (mServerManager.isLive()) {
            mHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    mServerBtn.setText(mPort + "服务器关闭(Local Server Demo in " + mPort + " Stop)");
                }
            });
        } else {
            mHandler.postTask(new Runnable() {
                @Override
                public void run() {
                    mServerBtn.setText(mPort + "服务器启动(Local Server Demo in " + mPort + " Start)");
                }
            });
        }
    }

    public ArrayList<InetAddress> getHostAddresss() {
      ArrayList<InetAddress> foundAddresses = new ArrayList<>();

        Enumeration<NetworkInterface> ifaces;
        try {
            ifaces = NetworkInterface.getNetworkInterfaces();
            while (ifaces.hasMoreElements()) {
                NetworkInterface iface = ifaces.nextElement();
                Enumeration<InetAddress> addresses = iface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress addr = addresses.nextElement();
                    if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) {
                        foundAddresses.add(addr);
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return foundAddresses;
    }

    private String getIpAddress() {
        NetHandle[] allNets = NetManager.getInstance(this).getAllNets();
        WifiDevice wifiDevice = WifiDevice.getInstance(this);

        // 判断是否有网络连接
        if (allNets.length > 0) {
            // wifi是否开启
            if (wifiDevice.isWifiActive()) {
                // wifi连接,否则为移动数据
                if (wifiDevice.isConnected()) {
                    Optional<IpInfo> ipInfo = wifiDevice.getIpInfo();
                    IpInfo wifiInfo = ipInfo.get();
                    int ipAddress = wifiInfo.getIpAddress();
                    if (ipAddress == 0) {
                        return "未连接wifi";
                    }
                    return ((ipAddress & 0xff) + "." + (ipAddress >> 8 & 0xff) + "."
                            + (ipAddress >> 16 & 0xff) + "." + (ipAddress >> 24 & 0xff));
                }
            } else {
                ArrayList<InetAddress> localData = getHostAddresss();
                InetAddress inetAddress = localData.get(0);
                return inetAddress.getHostAddress();
            }
        } else {
            return "当前无网络连接,请在设置中打开网络";
        }
        return "IP获取失败";
    }

    @Override
    protected void onActive() {
        super.onActive();
        flushServerText();
        mIPTv.setText("当前IP(Local Device IP):" + getIpAddress());
    }

    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_btn1:
                jumpOpen(SimpleDemo.class.getName());
                break;
            case ResourceTable.Id_btn2:
                jumpOpen(ComplexDemo.class.getName());
                break;
            case ResourceTable.Id_btn3:
                if (!mServerManager.isLive()) {
                    mServerManager.listen();
                } else {
                    mServerManager.shutdown();
                }
                break;
            case ResourceTable.Id_admin:
                jumpOpen(ServerAdmin.class.getName());
                break;
            case ResourceTable.Id_ip:
                SystemPasteboard systemPasteboard = SystemPasteboard.getSystemPasteboard(this);
                PasteData pasteData = PasteData.creatPlainTextData(mIPTv.getText().substring(5));
                systemPasteboard.setPasteData(pasteData);
                TextUtile textUtile = new TextUtile();
                textUtile.toastText("复制到剪切板",MainAbility.this);
                break;
            default:
                break;
        }
    }

    /**
     * 跳转
     *
     * @param abilityName ability页面
     */
    private void jumpOpen(String abilityName) {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(abilityName)
                .build();
        intent.setOperation(operation);
        startAbility(intent);
    }

    @Override
    public void onClientRead(OriginalData originalData, IClient client, IClientPool<IClient, String> clientPool) {
        String str = new String(originalData.getBodyBytes(), Charset.forName("utf-8"));
        JsonObject jsonObject = null;
        try {
            jsonObject = new JsonParser().parse(str).getAsJsonObject();
            int cmd = jsonObject.get("cmd").getAsInt();
            if (cmd == 54) { // 登陆成功
                String handshake = jsonObject.get("handshake").getAsString();
                HiLog.info(LABEL, Thread.currentThread().getName() + "接收到:"
                        + client.getHostIp() + " 握手信息:" + handshake);
            } else if (cmd == 14) { // 心跳
                HiLog.info(LABEL, Thread.currentThread().getName() + "接收到:" + client.getHostIp() + " 收到心跳");
            } else {
                HiLog.info(LABEL, Thread.currentThread().getName() + " 接收到:" + client.getHostIp() + "" + str);
            }
        } catch (Exception e) {
            HiLog.info(LABEL, Thread.currentThread().getName() + " 接收到:" + client.getHostIp() + "" + str);
        }
        MsgDataBean msgDataBean = new MsgDataBean(str);
        clientPool.sendToAll(msgDataBean);
    }

    @Override
    public void onClientWrite(ISendable sendable, IClient client, IClientPool<IClient, String> clientPool) {
        byte[] bytes = sendable.parse();
        bytes = Arrays.copyOfRange(bytes, 4, bytes.length);
        String str = new String(bytes, Charset.forName("utf-8"));
        JsonObject jsonObject = null;
        try {
            jsonObject = new JsonParser().parse(str).getAsJsonObject();
            int cmd = jsonObject.get("cmd").getAsInt();
            switch (cmd) {
                case 54: {
                    String handshake = jsonObject.get("handshake").getAsString();
                    HiLog.info(LABEL, Thread.currentThread().getName() + "发送给:" + client.getHostIp() + " 握手数据:" + handshake);
                    break;
                }
                default:
                    HiLog.info(LABEL, Thread.currentThread().getName() + " 发送给:" + client.getHostIp() + " " + str);
            }
        } catch (Exception e) {
            HiLog.info(LABEL, Thread.currentThread().getName() + " 发送给:" + client.getHostIp() + " " + str);
        }
    }
}
